#pragma once

#include "BoundedSpace.h"
#include "SpaceAgent.h"
#include <vector>
#include <cmath>

/*
  Copyright 2008 by Alexey Solovyev and University of Pittsburgh
  Licensed under the Academic Free License version 3.0
  See the file "LICENSE" for more information
*/

namespace org
{
	namespace spark
	{
		namespace space
		{



			/// <summary>
			/// Implementation of the space which behaves in the way similar to NetLogo, 
			/// that is, space is divided into cells but the agents can move
			/// inside each cell in the continuous manner.
			/// </summary>
			class GridSpace : public BoundedSpace
			{
			private:
				//static const long long serialVersionUID = 172987287392956066LL;
			protected:
				HashGrid2d *hashGrid;

				/// <summary>
				/// The default constructor </summary>
				/// <param name="xMin"> </param>
				/// <param name="xMax"> </param>
				/// <param name="yMin"> </param>
				/// <param name="yMax"> </param>
				/// <param name="wrapX"> </param>
				/// <param name="wrapY"> </param>
			public:
				GridSpace(double xMin, double xMax, double yMin, double yMax, bool wrapX, bool wrapY);


			protected:
				virtual void addNode0(SpaceNode *node);


				/// <summary>
				/// Removes the node from the space </summary>
				/// <param name="node"> </param>
				virtual void removeNode0(SpaceNode *node);


				virtual void addNodeAndMove0(SpaceNode *node);

				/// <summary>
				/// Changes the position of the node in the space </summary>
				/// <param name="node"> </param>
				virtual void changeNodePosition0(SpaceNode *node);



			//	private ArrayList<SpaceAgent> result = new ArrayList<SpaceAgent>(100);


				/// <summary>
				/// Gets all agents intersecting with the given space node </summary>
				/// <param name="node">
				/// @return </param>
				virtual std::vector<SpaceAgent*> getAgents(SpaceNode *node);

				/// <summary>
				/// Gets all agents of the given type intersecting with the space node </summary>
				/// <param name="node"> </param>
				/// <param name="type">
				/// @return </param>
// There is no native C++ template equivalent to generic constraints:
				template<typename T> where T : SpaceAgent
// Most Java annotations will not have direct native C++ equivalents:
//ORIGINAL LINE: @SuppressWarnings("unchecked") protected <T extends SpaceAgent> java.util.ArrayList<T> getAgents(SpaceNode node, Class type)
				virtual std::vector<T> getAgents(SpaceNode *node, Class *type);


				/// <summary>
				/// Gets all agents derived from the given type intersecting with the space node </summary>
				/// <param name="node"> </param>
				/// <param name="type">
				/// @return </param>
// There is no native C++ template equivalent to generic constraints:
				template<typename T> where T : SpaceAgent
// Most Java annotations will not have direct native C++ equivalents:
//ORIGINAL LINE: @SuppressWarnings("unchecked") protected <T extends SpaceAgent> java.util.ArrayList<T> getAgentsOfKind(SpaceNode node, Class type)
				virtual std::vector<T> getAgentsOfKind(SpaceNode *node, Class *type);


				/// <summary>
				/// Custom deserialization is needed.
				/// </summary>
			private:
				//void readObject(ObjectInputStream *ois) //throw(IOException, ClassNotFoundException);

				/// <summary>
				/// Custom serialization is needed.
				/// </summary>
				//void writeObject(ObjectOutputStream *oos) //throw(IOException);


			};

		}
	}
}
